package com.mo.star.ws;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mo.star.pojo.Message;
import com.mo.star.pojo.User;
import com.mo.star.service.MessageService;
import com.mo.star.service.UsertableService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.log4j.Log4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.sql.Date;
import java.time.LocalTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chat/{fromUserId}/{toUserId}")
@Log4j
@Component
public class ChatEdnPoint extends TextWebSocketHandler implements ApplicationContextAware {
    //记录当前连接数
    private static final  Map<String,Session> sessionMap = new ConcurrentHashMap<>();
    private static ApplicationContext applicationContext;
    private MessageService messageService;

    private UsertableService userService;
    @Override
   public  void setApplicationContext(ApplicationContext context) {
       ChatEdnPoint.applicationContext = context;
   }
    /**
     * 建立连接后调用
     * @param session
     */
    @OnOpen
    public void onOpen(Session session,
                       @PathParam("fromUserId") String fromUserId,
                       @PathParam("toUserId") String toUserId){
        log.info("放入map前"+sessionMap.size());
        //1.该userId必须是自己的userId，建立一个连接
        sessionMap.put(fromUserId, session);
        log.info("放入map后"+sessionMap.size());
        this.messageService =ChatEdnPoint.applicationContext.getBean(MessageService.class);
        this.userService = ChatEdnPoint.applicationContext.getBean(UsertableService.class);
        //2广播消息，告知好友上线
    }

    /**
     * 消息
     * @param message
     */
    @OnMessage
    public void onMessage(String message, Session session,
                          @PathParam("fromUserId") String fromUserId,
                          @PathParam("toUserId") String toUserId){
        if(message.equals("check")) {
            return;
        }
        JSONObject obj = JSON.parseObject(message);
        String content = obj.getString("content");
        //根据to用户名来获取session，再通过session发送消息文本,为什么要再转String
        Session toSession = sessionMap.get(String.valueOf(toUserId));
        if(toSession !=null){
            // 服务器端 再把消息组装一下，组装后的消息包含发送人和发送的文本内容
            User user  = userService.getUserById(fromUserId);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("sendUserId", fromUserId);
            jsonObject.put("receiveUserId", toUserId);
            jsonObject.put("avatarUrl", user.getAvatarUrl());
            jsonObject.put("userName", user.getUsername());
            jsonObject.put("content", content);
            jsonObject.put("position", "left");
            this.sendMessage(jsonObject.toString(),toSession);
        }else
            log.info(toUserId+"未登录");
        //消息持久化，放进数据库
        Message messageToSave = new Message();
        messageToSave.setSendUserId(fromUserId);
        messageToSave.setReceiveUserId(toUserId);
        messageToSave.setContent(content);
       messageService.doMessage(messageToSave);
       // boolean insert=messageService.save(messageToSave);
       // sendAllMessage(message);
        messageService.doChat(fromUserId,toUserId);
    }

    /**
     * 关闭连接后调用
     * @param session
     */
    @OnClose
    public void onClose(Session session, @PathParam("fromUserId") String fromUserId){
        sessionMap.remove(fromUserId);
        log.info("关闭连接");
    }
    /**
     * 服务端发送消息给客户端
     */
    private void sendMessage(String message, Session toSession) {
        try {
            log.info("服务端给客户端"+toSession.getId()+"发送消息\n"+message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }
    /**
     * 服务端发送消息给所有客户端
     */
    private void sendAllMessage(String message) {
        try {
            for (Session session : sessionMap.values()) {
               log.info("全部发送");
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
}
